// version=0.0.12
'use strict';


// const start_btn = document.getElementById("start_btn");
const call_btn = document.getElementById("call_btn");
const hangup_btn = document.getElementById("hangup_btn");
call_btn.addEventListener('click', call);
hangup_btn.addEventListener('click', hangup);
call_btn.disabled = false;
hangup_btn.disabled = true;

const i_candi_textarea = document.getElementById("input_candidate_textarea");
const c_i_candi_btn = document.getElementById("confirm_input_candidate_btn");
c_i_candi_btn.addEventListener('click', c_i_candi);
c_i_candi_btn.disabled = true;
i_candi_textarea.onchange = () => { c_i_candi_btn.disabled = false; };

const i_desc_textarea = document.getElementById("input_description_textarea");
const c_i_desc_btn = document.getElementById("confirm_input_description_btn");
c_i_desc_btn.addEventListener('click', c_i_desc);
c_i_desc_btn.disabled = true;
i_desc_textarea.onchange = () => { c_i_desc_btn.disabled = false; };

const local_video = document.getElementById("local_video");
const remote_video = document.getElementById("remote_video");


const self_desc_area = document.getElementById("self_description_str");
const self_candidate_area = document.getElementById("self_candidate_str");


function getSelectedSdpSemantics() {
    const sdpSemanticsSelect = document.getElementById('sdpSemantics');
    const option = sdpSemanticsSelect.options[sdpSemanticsSelect.selectedIndex];
    return option.value === '' ? {} : { sdpSemantics: option.value };
}
const StreamSourceSelect = document.getElementById('StreamSource');
StreamSourceSelect.onchange = start;
const stream_source = {
    camera: _getCameraStearm,
    screen: _getScreenCaptureStearm
}
function getSelectedStreamSource() {
    const option = StreamSourceSelect.options[StreamSourceSelect.selectedIndex];
    return stream_source[option.value]
}

let pc;
function make_pc(local_stream, proactive = true) {
    const config = Object.assign({
        iceServers: [{ urls: "stun:stun.ideasip.com" }]
    }, getSelectedSdpSemantics());
    const pc = new RTCPeerConnection(config);
    log("生成pc，配置为:" + JSON.stringify(config) + "\tproactive:" + proactive);
    pc.ontrack = ({ track, streams }) => {
        track.onunmute = () => {
            if (remote_video.srcObject) {
                return;
            }
            remote_video.srcObject = streams[0];
        };
    };
    // let self_info_obj = {
    //     desc: null,
    //     candidates: []
    // }
    if (proactive) {
        pc.onnegotiationneeded = async () => {
            const offer = await pc.createOffer()
            await pc.setLocalDescription(offer);
            self_desc_area.innerHTML = JSON.stringify(pc.localDescription);
            log("self_description(offer)已生成")
        };
    }

    let self_candidates = [];
    pc.onicecandidate = ({ candidate }) => {
        // self_info_obj.candidates.push(candidate);
        // alert("生成了新的candidate")
        self_candidates.push(candidate)
        if (candidate) {
            self_candidate_area.innerHTML = JSON.stringify(self_candidates);
        } else {
            log("本轮candidate生成完毕,共" + self_candidates.length + "个!")
            self_candidates = [];
        }

        // self_info.innerHTML = JSON.stringify(self_info_obj);
    };

    local_stream.getTracks().forEach(track => pc.addTrack(track, local_stream));
    log("媒体Track加入pc");

    return pc;
}


// async function start() {

// }
async function _getScreenCaptureStearm() {
    if (navigator.getDisplayMedia) {
        return navigator.getDisplayMedia({ video: true });
    } else if (navigator.mediaDevices.getDisplayMedia) {
        return navigator.mediaDevices.getDisplayMedia({ video: true });
    } else {
        return navigator.mediaDevices.getUserMedia({ video: { mediaSource: 'screen' } });
    }
}

async function _getCameraStearm() {
    const audioSource = audioInputSelect.value;
    const videoSource = videoSelect.value;
    return await navigator.mediaDevices.getUserMedia(
        {
            audio: { deviceId: audioSource ? { exact: audioSource } : undefined },
            video: { deviceId: videoSource ? { exact: videoSource } : undefined }
        }
    );
}


async function start() {
    call_btn.disabled = true;
    hangup_btn.disabled = false;
    // 采集视频并本地显示
    local_stream = await getSelectedStreamSource()()

    // 
    local_video.srcObject = local_stream;

    navigator.mediaDevices.enumerateDevices().then(gotDevices);
}

let local_stream;
async function call() {
    await start();
    pc = make_pc(local_stream);


}

async function c_i_candi() {
    const input_candidates = JSON.parse(i_candi_textarea.value);
    for (const i in input_candidates) {

        if (input_candidates[i]) {
            await pc.addIceCandidate(input_candidates[i]);
        }
    }
    log("远程candidates已加入")
}

async function c_i_desc() {
    const input_description = JSON.parse(i_desc_textarea.value);

    if (input_description.type == "offer") {
        // await pc.setLocalDescription({type: "rollback"})
        pc = make_pc(local_stream, false);
        await pc.setRemoteDescription(input_description);
        const answer = await pc.createAnswer()
        await pc.setLocalDescription(answer);
        self_desc_area.innerHTML = JSON.stringify(pc.localDescription);
        log("offer description已处理，answer description已生成，请回复");
    } else {
        await pc.setRemoteDescription(input_description);
        log("answer description已处理");
    }
}

function hangup() {
    if (remote_video.srcObject) {
        remote_video.srcObject.getTracks().forEach(track => track.stop());
    }

    if (local_video.srcObject) {
        local_video.srcObject.getTracks().forEach(track => track.stop());
    }
    hangup_btn.disabled = true;
    call_btn.disabled = false;

    pc = undefined;
    log("pc已销毁")
}







const audioInputSelect = document.getElementById('audioSource');
const audioOutputSelect = document.getElementById('audioOutput');
const videoSelect = document.getElementById('videoSource');
const selectors = [audioInputSelect, audioOutputSelect, videoSelect];

audioInputSelect.onchange = start;
videoSelect.onchange = start;

function gotDevices(deviceInfos) {
    // Handles being called several times to update labels. Preserve values.
    var values = selectors.map(function (select) {
        return select.value;
    });
    selectors.forEach(function (select) {
        while (select.firstChild) {
            select.removeChild(select.firstChild);
        }
    });
    for (let i = 0; i < deviceInfos.length; i++) {
        const deviceInfo = deviceInfos[i];
        const option = document.createElement('option');
        option.value = deviceInfo.deviceId;
        if (deviceInfo.kind === 'audioinput') {
            option.text = deviceInfo.label ||
                'microphone ' + (audioInputSelect.length + 1);
            audioInputSelect.appendChild(option);
        } else if (deviceInfo.kind === 'audiooutput') {
            option.text = deviceInfo.label || 'speaker ' +
                (audioOutputSelect.length + 1);
            audioOutputSelect.appendChild(option);
        } else if (deviceInfo.kind === 'videoinput') {
            option.text = deviceInfo.label || 'camera ' + (videoSelect.length + 1);
            videoSelect.appendChild(option);
        } else {
            console.log('Some other kind of source/device: ', deviceInfo);
        }
    }
    selectors.forEach(function (select, selectorIndex) {
        if (Array.prototype.slice.call(select.childNodes).some(function (n) {
            return n.value === values[selectorIndex];
        })) {
            select.value = values[selectorIndex];
        }
    });
}


navigator.mediaDevices.enumerateDevices().then(gotDevices);